﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

using TTGame;

/*
 * SkillReleaseData
 *
 *
 * 依赖：
 * skill,puppet
 *
 * ！不写重复代码！
 * @author TTun
 * @date 7/12/2017 5:16:56 PM
 */
namespace TTGameEngine {

public enum SkillShapeID : byte {
    none,               //无
    Shape_circle = 1,   //圆形
    Shape_rectangle,    //矩形
}

public enum SkillCampID : byte {
    enemyCamp = 0,  //敌方
    SelfCamp,       //本方
}

public class SkillAttackFrameInfo {
    public float startTime;
    public string frameName; //子弹名
    public byte bytepar1; // campType | shootNUmber
    public byte bytepar2; // shapeID | speed
    public float value1;
    public float value2;
    public int intpar1;
}

public class SkillReleaseData {
    public SkillConfigInfo info;
    public SkillAttackFrameInfo[] attackInfo;
    public Puppet owner;
    public float curentCDTime;
    public float curentRelaseTime;

    public SkillReleaseData releationData;

    //特效记录
//     public List<EffectSetting> effectSetList = new List<EffectSetting>();
//     public List<EffectScript> effectList = new List<EffectScript>();
//     //声音延迟
//     public List<SkillAudioSetting> audioDelayList = new List<SkillAudioSetting>();

    public bool isNormalAttack;//每个人一个普攻
    public bool activeFrame = false;

    public int attackFrameIndex = -1;
#if UNITY_EDITOR
    public float shapeGUIRadius;
    public List<Vector3> shapeGUIPoints = new List<Vector3>();
#endif

    public bool IsLock {
        get { return info.lockType != ELockTagetType.eLT_NoTarget; }
    }

    //是否增益
    public bool IsCure {
        get { return info.skillCampType == SkillCampID.SelfCamp; }
    }

    public SkillReleaseData(Puppet obj, SkillConfigInfo _info) {
        owner = obj;
        info = _info;
        curentCDTime = 0f;
        info.OnInitData();
        RebuildAttackFrameInfo();
        if(info.relationSkillID >= 0) {
            SkillConfigInfo relationInfo = SkillReadInfo.Instance.GetSkillInfo((uint)info.relationSkillID);
            if(relationInfo != null) {
                releationData = new SkillReleaseData(obj, relationInfo);
            }
        }
    }

#if UNITY_EDITOR
    public void ClearGUI() {
        shapeGUIPoints.Clear();
    }

    public void DrawGUI() {
        Gizmos.color = Color.green;
        if(shapeGUIPoints.Count == 1) {
            Gizmos.DrawWireSphere(shapeGUIPoints[0], shapeGUIRadius);
        } else {
            for(int i = 0; i < shapeGUIPoints.Count; i++) {
                Vector3 p = shapeGUIPoints[i];
                Vector3 q = shapeGUIPoints[(i + 1) % shapeGUIPoints.Count];
                Gizmos.DrawLine(p, q);
            }
        }
    }
#endif
    public void RebuildAttackFrameInfo() {
        if(info.attackFrameInfo != null && info.attackFrameInfo.Length > 0) {
            int count = info.attackFrameInfo.Length;
            attackInfo = new SkillAttackFrameInfo[count];
            for(int i = 0; i < count; i++) {
                SkillAttackFrameInfo frame = new SkillAttackFrameInfo();
                string[] buffer = info.attackFrameInfo[i].Split(GameConstant.SplitVar, StringSplitOptions.RemoveEmptyEntries);
                frame.startTime = float.Parse(buffer[0]);
                switch(info.skillType) {
                    case ESkillType.eST_NormalFly:
                        frame.frameName = buffer[1];
                        if(buffer.Length > 2) {
                            frame.bytepar1 = byte.Parse(buffer[2]);//发射数量
                            frame.value1 = float.Parse(buffer[3]);//发射间隔
                        } else {
                            frame.bytepar1 = 1;
                            frame.value1 = 0f;
                        }
                        break;
                    case ESkillType.eST_NormalArea://普通群体
                        frame.bytepar1 = byte.Parse(buffer[1]);//攻击阵营
                        frame.bytepar2 = byte.Parse(buffer[2]);//形状类型
                        frame.value1 = float.Parse(buffer[3]);//形状参数1
                        frame.value2 = float.Parse(buffer[4]);//形状参数2
                        break;
                    case ESkillType.eST_FollowArea://跟随群体
                        frame.bytepar1 = byte.Parse(buffer[1]); //跟随阵营
                        frame.bytepar2 = byte.Parse(buffer[2]);//跟随速度
                        frame.value1 = float.Parse(buffer[3]);//持续时间
                        frame.value2 = float.Parse(buffer[4]);//计算间隔
                        break;
                    case ESkillType.eST_Teleport://瞬移
                        frame.value1 = float.Parse(buffer[1]);//消失时间
                        frame.value2 = float.Parse(buffer[2]);//与目标之间距离值
                        if(buffer.Length > 3) {
                            frame.frameName = buffer[3];//伴随特效
                            frame.bytepar1 = byte.Parse(buffer[4]);//对象身上的挂靠点
                        }
                        break;
                    case ESkillType.eST_RunAttack://冲撞
                        frame.bytepar1 = byte.Parse(buffer[1]);//冲撞速度 0-255
                        frame.intpar1 = int.Parse(buffer[2]);//冲撞中的受伤id <0为不受伤
                        frame.value1 = float.Parse(buffer[3]);//冲撞范围
                        frame.value2 = float.Parse(buffer[4]);//距离多少停下
                        break;
                }
                attackInfo[i] = frame;
            }
            System.Array.Sort(attackInfo, delegate(SkillAttackFrameInfo info1, SkillAttackFrameInfo info2) {
                if(info1.startTime < info2.startTime) {
                    return -1;
                }
                return 1;
            });
        }
    }

    public void OnUpdate(float dt) {
        if(curentCDTime >= 0f) { curentCDTime -= dt; }

        if(activeFrame) {
            curentRelaseTime += dt;
            OnUpdateAttackFrame();
        }

        OnUpdateDealyEffect(dt);
        OnUpdateDealyAudio(dt);
#if UNITY_EDITOR
        if(shapeGUIPoints.Count > 0 && curentCDTime < 0) {
            ClearGUI();
        }
#endif
        if(releationData != null) {
            releationData.OnUpdate(dt);
        }
    }

    public bool IsCanRelease(bool condition = true) {
        if(curentCDTime > 0f) {
            return false;
        }

//         if(!isNormalAttack) {
//             if(owner.buffManage.IsTrigger(BuffTypeID.Silence))
//                 return false;//沉默不能释放除普攻外的技能
//         } else {
//             if(owner.buffManage.IsTrigger(BuffTypeID.Disarm)) {
//                 return false;
//             }
//         }
//
//         if(IsLock && !IsCure) {
//             //锁定目标的技能判断是否有目标
//             if(!owner.threadInfo.IsThread) {
//                 return false;
//             }
//         }

        if(condition) {
            //不检查条件
            return info.CheckCondition(owner);
        }

        return true;
    }

    public void CastRelationData() {
        if(releationData != null) {
            releationData.curentCDTime = -1f;
            if(releationData.IsCanRelease(false)) {
                owner.t_curGCD = -1f;
                //owner.m_puppetAI.forceReleaseData = releationData;
            }
        }
    }

    public void ReleaseFrame() {
        if(attackInfo == null || attackInfo.Length == 0) {
            return;
        }
        activeFrame = true;
        attackFrameIndex = 0;
        curentRelaseTime = 0f;
    }

    public void ReleaseFrameOver() {
        activeFrame = false;
        curentRelaseTime = 0f;
        attackFrameIndex = 0;
    }

    public void OnUpdateAttackFrame() {
        while(attackFrameIndex < attackInfo.Length) {
            if(attackInfo[attackFrameIndex].startTime < curentRelaseTime) {
                OnAttackFrame(attackFrameIndex);
                attackFrameIndex++;
                if(attackFrameIndex == attackInfo.Length) {
                    ReleaseFrameOver();
                }
            } else {
                break;
            }
        }
    }


    public void OnReleaseSkill() {
        curentCDTime = info.cdTime;
        if(IsLock && owner.Locker != null && owner.Locker != owner) {
            //立即设置更改面向朝向攻击者
            Vector3 releaseDirection = (owner.Locker.objTF.position - owner.objTF.position).normalized;
            owner.objTF.rotation = Quaternion.LookRotation(releaseDirection);
        }
        if(string.IsNullOrEmpty(info.prepareAnimName)) {
            owner.SetState(PuppetStateID.Skill);
        } else {
            //owner.SetState(PuppetStateID.Prepare);
        }
    }

    public void OnAttackFrame(int index) {
        if(index >= attackInfo.Length) {
            return;
        }
//         SkillAttackFrameInfo frame = attackInfo[index];
//         if(info.skillType == ESkillType.eST_NormalHandFight) {
//             // 普通触发攻击   近身攻击|直接上buff|直接加血
//             OnAttackTriggerFrame();
//         } else if(info.skillType == ESkillType.eST_NormalFly) {
//             //普通触发子弹   远程攻击|丢弹加Buff
//             owner.SkillControl.SetIEnumeratorAction(frame, SkillActionTYpeID.Action_ShootBullets);
//         } else if(info.skillType == ESkillType.eST_SingleNoTarget) {
//             //单体无目标 选定目标 做对应操作
//
//         } else if(info.skillType == ESkillType.eST_NormalArea) {
//             //普通群体
//             OnAttackShapeFrame((SkillCampID)frame.bytepar1, (SkillShapeID)frame.bytepar2, frame.value1, frame.value2);
//         } else if(info.skillType == ESkillType.eST_FollowArea) {
//             //跟随群体
//             owner.SkillControl.SetIEnumeratorAction(frame, SkillActionTYpeID.Action_FollowArea);
//         } else if(info.skillType == ESkillType.eST_Teleport) {
//             //瞬移
//             owner.SkillControl.SetIEnumeratorAction(frame, SkillActionTYpeID.Action_Teleport);
//         } else if(info.skillType == ESkillType.eST_RunAttack) {
//             //冲撞
//             owner.SkillControl.SetIEnumeratorAction(frame, SkillActionTYpeID.Action_RunAttack);
//         }
    }

    public void OnAttackTriggerFrame() {
//         Puppet obj = null;
//         if(IsLock) {
//             if(owner.Locker != null) {
//                 obj = owner.Locker;
//             } else { DebugUtil.LogError("攻击对象丢失！"); }
//         } else {
//             List<Puppet> objs = PuppetManager.Instance.GetSkillList(owner.campID, info.skillCampType, owner.IsCharm, owner.objTF, info.range);
//             if(IsCure && objs.Count > 1) {
//                 objs.Remove(owner);
//             }
//             obj = objs.getObjNearWithDirection(owner);
//         }
//         if(obj != null) {
//             DamageResult result = DamageResult.CreateDamageResult(obj, this);
//             obj.OnDamage(result);
//         }
    }

    public void OnAttackShapeFrame(SkillCampID groupID, SkillShapeID shapId, float value1, float value2) {
//         Vector3 releasePosition = Vector3.zero;
//         if(IsLock) {
//             if(owner.Locker != null) {
//                 releasePosition = owner.Locker.objTF.position;
//             }
//         } else {
//             releasePosition = owner.objTF.position;
//         }
//         List<Puppet> tempList = PuppetManager.Instance.GetSkillList(owner.campID, groupID, owner.campID != owner.recordCampID);
//         List<Puppet> objList = new List<Puppet>();
//         if(shapId == SkillShapeID.Shape_circle) {
// #if UNITY_EDITOR
//             shapeGUIPoints.Add(releasePosition);
//             shapeGUIRadius = value1;
// #endif
//             for(int i = 0; i < tempList.Count; i++) {
//                 Vector3 tempPos = tempList[i].objTF.position;
//                 if(releasePosition.distanceLess(tempPos, value1) && IsPointInCircularSector(tempPos, value2)) {
//                     objList.Add(tempList[i]);
//                 }
//             }
//         } else if(shapId == SkillShapeID.Shape_rectangle) {
//             if(IsLock) {
//                 if(owner.Locker != null) {
// #if UNITY_EDITOR
//                     shapeGUIPoints.Add(owner.Locker.objTF.position + new Vector3(-value2, 0, -value1));
//                     shapeGUIPoints.Add(owner.Locker.objTF.position + new Vector3(-value2, 0, value1));
//                     shapeGUIPoints.Add(owner.Locker.objTF.position + new Vector3(value2, 0, value1));
//                     shapeGUIPoints.Add(owner.Locker.objTF.position + new Vector3(value2, 0, -value1));
// #endif
//                     //锁定 取目标矩形
//                     for(int i = 0; i < tempList.Count; i++) {
//                         Vector3 tempPos = tempList[i].objTF.position;
//                         float v1 = Mathf.Abs(owner.Locker.objTF.position.z - tempPos.z);
//                         float v2 = Mathf.Abs(owner.Locker.objTF.position.x - tempPos.x);
//                         if(v1 < value1 && v2 < value2) {
//                             objList.Add(tempList[i]);
//                         }
//                     }
//                 }
//             } else {
//                 //不锁定 取自身面向的矩形
//                 Vector3[] p = new Vector3[4];
//                 p[0] = owner.objTF.position + Quaternion.Euler(0f, -90f, 0f) * owner.objTF.forward * value2 / 2;
//                 p[1] = p[0] + (owner.objTF.position - p[0]).normalized * value2;
//                 p[2] = p[1] + owner.objTF.forward * value1;
//                 p[3] = p[0] + owner.objTF.forward * value1;
// #if UNITY_EDITOR
//                 shapeGUIPoints.Add(p[0]);
//                 shapeGUIPoints.Add(p[1]);
//                 shapeGUIPoints.Add(p[2]);
//                 shapeGUIPoints.Add(p[3]);
// #endif
//                 for(int i = 0; i < tempList.Count; i++) {
//                     if(tempList[i].objTF.position.IsInPolygon(p)) {
//                         objList.Add(tempList[i]);
//                     }
//                 }
//             }
//         }
//         for(int i = 0; i < objList.Count; i++) {
//             DamageResult result = DamageResult.CreateDamageResult(objList[i], this);
//             objList[i].OnDamage(result);
//         }
    }

    //点是否与释放对象夹角小于angle
    bool IsPointInCircularSector(Vector3 p, float angle) {
        if(angle >= 360f) { return true; }
        if (angle == 180) { return owner.objTF.position.IsSameDirection(p); }
        Vector3 vectory = p - owner.objTF.position;
        float realAngle = Vector3.Angle(owner.objTF.forward, vectory);
        return realAngle < angle / 2;
    }

    //找寻技能锁定的对象
    public Puppet GetLocker() {
        ELockTagetType type = info.lockType;
        Puppet tempLock = null;
        int index = info.lockPrior - 1;
//         List<Puppet> tempList = ObjectManager.Share().GetSkillCampObjList(this);
//         if(tempList != null && tempList.Count == 0) {
//             return null;
//         }
//         switch(type) {
//             case ELockTagetType.eLT_Self:
//                 tempLock = owner;
//                 break;
//             case ELockTagetType.eLT_Target:
//                 if(IsCure && tempList.Count > 1) {
//                     tempList.Remove(owner);
//                 }
//                 tempLock = tempList.getObjNear(owner);
//                 break;
//             case ELockTagetType.eLT_Target_Near:
//                 tempList.objNearSort(owner);
//                 if(index >= tempList.Count) {
//                     index = tempList.Count - 1;
//                 }
//                 tempLock = tempList[index];
//                 break;
//             case ELockTagetType.eLT_Tagret_Hp:
//                 tempList.objHpSort();
//                 if(index >= tempList.Count) {
//                     index = tempList.Count - 1;
//                 }
//                 tempLock = tempList[index];
//                 break;
//             case ELockTagetType.eLT_Target_Random:
//                 int randomIndex = UnityEngine.Random.Range(0, tempList.Count);
//                 tempLock = tempList[randomIndex];
//                 break;
//             case ELockTagetType.eLT_Target_Attrubte:
//                 //后续
//                 break;
//        }
//        return tempLock;
        return null;
    }


    public EffectScript PlaySkillEffect(string effectName, EffectSetting setting = null) {
//         if(!string.IsNullOrEmpty(effectName)) {
//             EffectScript esIns = ScenebattleSetting.Self.CreateSceneEffect(owner, GameConstant.RELEASE_PREFAB_PATH + effectName);
//             if(esIns) {
//                 if(setting != null) {
//                     if(setting.pointType != PuppetPointType.None) {
//                         Transform node = owner.GetRelationTF(setting.pointType);
//                         if(setting.parentFlag) {
//                             esIns.SetParent(node, Vector3.zero);
//                         } else {
//                             esIns.transform.position = node.position;
//                         }
//                     }
//                     switch(setting.dirType) {
//                         case DirectionType.Forward:
//                             esIns.transform.rotation = Quaternion.LookRotation(owner.objTF.forward);
//                             break;
//                     }
//                 }
//                 effectList.Add(esIns);
//                 return esIns;
//             }
//         }
        return null;
    }


    public EffectScript PlaySettingEffect(int index) {
        EffectSetting setting = null;
        if(index == 0) {
            setting = info.pESetting;
        } else if(index == 1) {
            setting = info.aESetting;
        } else if(index == 2) {
            setting = info.rESetting;
        }
        if(!string.IsNullOrEmpty(setting.effectName)) {
            if(setting.delayTime <= 0) {
                return PlaySkillEffect(setting.effectName, setting);
            } else {
                setting.curentDelayTime = setting.delayTime;
                //effectSetList.Add(setting);
            }
        }
        return null;
    }


    public void OnUpdateDealyEffect(float dt) {
//         for(int i = effectSetList.Count - 1; i >= 0; i--) {
//             EffectSetting setting = effectSetList[i];
//             setting.curentDelayTime -= dt;
//             if(setting.curentDelayTime < 0f) {
//                 PlaySkillEffect(setting.effectName, setting);
//                 effectSetList.RemoveAt(i);
//             }
//         }
    }

    public void OnInterrupt(bool relationFlag = false) {
//         owner.SkillControl.StopWorking();
//         ReleaseFrameOver();
//         RemoveAllEffect();
//         if(relationFlag && releationData != null) {
//             releationData.OnInterrupt(true);
//         }
    }

    public void RemoveAllEffect() {
//         effectSetList.Clear();
//         for(int i = 0; i < effectList.Count; i++) {
//             //清理一遍
//             if(effectList[i]) {
//                 effectList[i].OnDeactive();
//             }
//         }
//         effectList.Clear();
    }

    public void OnUpdateDealyAudio(float dt) {
//         for(int i = audioDelayList.Count - 1; i >= 0; i--) {
//             SkillAudioSetting set = audioDelayList[i];
//             audioDelayList[i].delayTime -= dt;
//             if(set.delayTime < 0f) {
//                 AudioSourceExtensions.PlayClip(set.audioName, owner.objTF);
//                 audioDelayList.RemoveAt(i);
//             }
//         }
    }

    public void PlaySkillAudio(string name, float delay = 0f) {
//         if(string.IsNullOrEmpty(name)) {
//             return;
//         }
//         if(delay > 0f) {
//             SkillAudioSetting set = new SkillAudioSetting(name, delay);
//             audioDelayList.Add(set);
//         } else {
//             AudioSourceExtensions.PlayClip(name, owner.objTF);
//         }
    }

}

}